import pandas as pd
import os
import time
import sys
import re
import numpy as np

# reference
# 1、 https://blog.csdn.net/brucewong0516/article/details/84768464 详解pandas.DataFrame.resample根据时间聚合采样
# 2、 https://blog.csdn.net/the_time_runner/article/details/86619766  Pandas.df.resample()错误TypeError: Only valid with DatetimeIndex, TimedeltaIndex or PeriodIndex, but got an instance of ‘Index’【已解决】
# 3、https://www.cnblogs.com/Cheryol/p/13508151.html 重采样（resampling）指的是将时间序列从一个频率转换到另一个频率的过程，OHLC重采样


symbol_trade_time = {}
symbol_trade_list = []


def build_trade_time():
    ### "trade time reference "
    # from http://qhsxf.com/%E6%9C%9F%E8%B4%A7%E4%BA%A4%E6%98%93%E6%97%B6%E9%97%B4.html
    # from http://www.fcqihuo.com/ncqh/uploads/a/futuresAnswer/2020/0828/16802.html

    # 没有夜盘
    trade_time_0 = {"night_trade_start_datetime": "09:00:00",
                    "night_trade_end_datetime": "09:00:00",
                    "morning_trade_start_datetime": "09:00:00",
                    "morning_break_start_datetime": "10:15:00",
                    "morning_break_end_datetime": "10:30:00",
                    "morning_trade_end_datetime": "11:30:00",
                    "afternoon_trade_start_datetime": "13:30:00",
                    "afternoon_trade_end_datetime": "15:00:00"}

    # 夜盘为 21：00：00 到 23：00：00
    trade_time_1 = {"night_trade_start_datetime": "21:00:00",
                    "night_trade_end_datetime": "23:00:00",
                    "morning_trade_start_datetime": "09:00:00",
                    "morning_break_start_datetime": "10:15:00",
                    "morning_break_end_datetime": "10:30:00",
                    "morning_trade_end_datetime": "11:30:00",
                    "afternoon_trade_start_datetime": "13:30:00",
                    "afternoon_trade_end_datetime": "15:00:00"}

    # 夜盘为 21：00：00 到 1：00：00
    trade_time_2 = {"night_trade_start_datetime": "21:00:00",
                    "night_trade_end_datetime": "1:00:00",
                    "morning_trade_start_datetime": "09:00:00",
                    "morning_break_start_datetime": "10:15:00",
                    "morning_break_end_datetime": "10:30:00",
                    "morning_trade_end_datetime": "11:30:00",
                    "afternoon_trade_start_datetime": "13:30:00",
                    "afternoon_trade_end_datetime": "15:00:00"}

    # 夜盘为 21：00：00 到 2：30：00
    trade_time_3 = {"night_trade_start_datetime": "21:00:00",
                    "night_trade_end_datetime": "2:30:00",
                    "morning_trade_start_datetime": "09:00:00",
                    "morning_break_start_datetime": "10:15:00",
                    "morning_break_end_datetime": "10:30:00",
                    "morning_trade_end_datetime": "11:30:00",
                    "afternoon_trade_start_datetime": "13:30:00",
                    "afternoon_trade_end_datetime": "15:00:00"}

    # 夜盘无，没有breaktime 早盘 9:30-11:30  下午盘 13:00 - 15:00
    trade_time_4 = {"night_trade_start_datetime": "09:00:00",
                    "night_trade_end_datetime": "09:00:00",
                    "morning_trade_start_datetime": "09:30:00",
                    "morning_break_start_datetime": "10:00:00",
                    "morning_break_end_datetime": "10:00:00",
                    "morning_trade_end_datetime": "11:30:00",
                    "afternoon_trade_start_datetime": "13:00:00",
                    "afternoon_trade_end_datetime": "15:00:00"}

    # 夜盘无，没有breaktime 早盘 9:15-11:30  下午盘 13:00 - 15:15
    trade_time_5 = {"night_trade_start_datetime": "09:00:00",
                    "night_trade_end_datetime": "09:00:00",
                    "morning_trade_start_datetime": "09:15:00",
                    "morning_break_start_datetime": "10:00:00",
                    "morning_break_end_datetime": "10:00:00",
                    "morning_trade_end_datetime": "11:30:00",
                    "afternoon_trade_start_datetime": "13:00:00",
                    "afternoon_trade_end_datetime": "15:15:00"}

    SymbolInTradeTime0 = ["SM","SF","WH","JR","LR","PM","RI","RS","UR","CJ","AP",\
                          "bb","fb","lh","jd",\
                          "wr",\
                          ]
    for symbol in SymbolInTradeTime0:
        symbol_trade_time[symbol] = trade_time_0


    SymbolInTradeTime1 = ["FG","SA","MA","SR","TA","RM","OI","CF","CY","PF","ZC",\
                           "i","j","jm","a","b","m","p","y","c","cs","pp","v","eb","eg","pg","rr","l",\
                           "fu","ru","bu","sp","rb","hc",\
                           "lu","nr"]
    for symbol in SymbolInTradeTime1:
        symbol_trade_time[symbol] = trade_time_1


    SymbolInTradeTime2 = ["cu","pb","al","zn","sn","ni","ss",\
                          "bc"]
    for symbol in SymbolInTradeTime2:
        symbol_trade_time[symbol] = trade_time_2

    
    SymbolInTradeTime3 = ["cu","pb","al","zn","sn","ni","ss","au","ag",\
                          "sc",]
    for symbol in SymbolInTradeTime3:
        symbol_trade_time[symbol] = trade_time_3

    SymbolInTradeTime4 = ["IF","IC","IH"]
    for symbol in SymbolInTradeTime4:
        symbol_trade_time[symbol] = trade_time_4
   
    SymbolInTradeTime5 = ["T","TF","TS"]
    for symbol in SymbolInTradeTime5:
        symbol_trade_time[symbol] = trade_time_5

    return symbol_trade_time


NIGHT_ABNORMAL_DATES = []


def get_trade_time(symbol):
    """ 
    Return trade datettime includes: night/day open, close datetime
    if no break in morning, moring break start/end datetime would be set as monring_trade_end_time
    """
    # Code begins
    trade_date = "1.1"
    if trade_date in NIGHT_ABNORMAL_DATES:
        return None

    if symbol not in list(symbol_trade_time.keys()):
        return None

    # return (night_trade_start_datetime, night_trade_end_datetime, morning_trade_start_datetime,
    #morning_break_start_datetime, morning_break_end_datetime, morning_trade_end_datetime,
    # afternoon_trade_start_datetime, afternoon_trade_end_datetime)
    return list(symbol_trade_time[symbol].values())


def raw2tick(df, symbol='IH'):
    """
    Input: a raw DataFrame downloaded from DataVendor
    Returns: a DataFrame with data only in market open time
    """
    # Code begins

    night_trade_start_datetime, night_trade_end_datetime, morning_trade_start_datetime, morning_break_start_datetime, \
        morning_break_end_datetime, morning_trade_end_datetime, afternoon_trade_start_datetime, afternoon_trade_end_datetime = get_trade_time(
            symbol)

    if(night_trade_start_datetime <= night_trade_end_datetime):
        dflogic = ((df.time >= night_trade_start_datetime) & (df.time < night_trade_end_datetime)) | \
        ((df.time >= morning_trade_start_datetime) & (df.time < morning_break_start_datetime)) | \
        ((df.time >= morning_break_end_datetime) & (df.time < morning_trade_end_datetime)) | \
        ((df.time >= afternoon_trade_start_datetime) & (df.time < afternoon_trade_end_datetime)) | \
        ((df.time == night_trade_end_datetime) & (df.millisecond == 0)) | \
        ((df.time == morning_break_start_datetime) & (df.millisecond == 0)) | \
        ((df.time == morning_trade_end_datetime) & (df.millisecond == 0)) | \
        ((df.time == afternoon_trade_end_datetime) & (df.millisecond == 0))
        dfremain = df.loc[dflogic]
        dfout = df.loc[~dflogic]
    else:  # cross '00:00:00'
        dflogic = ((df.time >= night_trade_start_datetime) & (df.time <= '23:59:59')) | \
        ((df.time >= '00:00:00') & (df.time < night_trade_end_datetime)) | \
        ((df.time >= morning_trade_start_datetime) & (df.time < morning_break_start_datetime)) | \
        ((df.time >= morning_break_end_datetime) & (df.time < morning_trade_end_datetime)) | \
        ((df.time >= afternoon_trade_start_datetime) & (df.time < afternoon_trade_end_datetime)) | \
        ((df.time == night_trade_end_datetime) & (df.millisecond == 0)) | \
        ((df.time == morning_break_start_datetime) & (df.millisecond == 0)) | \
        ((df.time == morning_trade_end_datetime) & (df.millisecond == 0)) | \
        ((df.time == afternoon_trade_end_datetime) & (df.millisecond == 0))
        dfremain = df.loc[dflogic]
        dfout = df.loc[~dflogic]

    return [dfremain, dfout]


def tick2min(df):
    """
    Input: a raw DataFrame of market tick data
    Returns: a DataFrame with Open High Low Close price sampled by 1 minute
    resample
    Note:
    1. minute begins: 09:01:00,000, should be included in first minute

    """
    # Code begins
    #df = df.set_index('time')
    df['candle_begin_time_GMT8'] = pd.to_datetime(df['time'])
    df = df.set_index('candle_begin_time_GMT8')
    df_ohlc = (df['last_price'].resample(
        "1min", label='right', closed='right').ohlc()).dropna()
    df_vol_turnover = (df[['volume', 'turnover']].resample(
        "1min", label='right', closed='right').sum()).dropna()
    df_vol_turnover = df_vol_turnover[~(df_vol_turnover == 0).all(axis=1)]

    df_date_time = (df[['trade_date', 'time']].resample(
        "1min", label='right', closed='right').last()).dropna()
    dfdata = df_ohlc.merge(df_vol_turnover, left_index=True, right_index=True)
    dfdata = dfdata.merge(df_date_time,left_index=True, right_index=True)



    return dfdata





if __name__ == '__main__':

    build_trade_time()

    df = pd.read_csv('./data/input/dc/a1801_20180102.csv', encoding='gb2312')
    df.columns = ['trade_date', 'symbol', 'exchange', 'symbol_in_exchange', 'last_price', 'prev_settle', 'prev_close', 'prev_open_interest',
                  'open', 'high', 'low', 'volume', 'turnover', 'open_interest', 'close', 'settle', 'limit_up',
                  'limit_down', 'prev_otm', 'otm', 'time', 'millisecond', 'bid_price1', 'bid_volume1', 'ask_price1', 'ask_volume1',
                  'bid_price2', 'bid_volume2', 'ask_price2', 'ask_volume2', 'bid_price3', 'bid_volume4', 'ask_price3', 'ask_volume3',
                  'bid_price4', 'bid_volume4', 'ask_price4', 'ask_volume4', 'bid_price5', 'bid_volume5', 'ask_price5', 'ask_volume5',
                  'avg_price', 'date']

    df['avg_price2'] = df.turnover / df.volume

    COLS_TO_DROP = ['exchange', 'symbol_in_exchange', 'bid_price2', 'bid_volume2', 'ask_price2', 'ask_volume2',
                    'bid_price3', 'bid_volume4', 'ask_price3', 'ask_volume3', 'bid_price4', 'bid_volume4',
                    'ask_price4', 'ask_volume4', 'bid_price5', 'bid_volume5', 'ask_price5', 'ask_volume5',
                    'prev_otm', 'otm', 'close', 'settle']
    df = df.drop(COLS_TO_DROP, axis=1)

    tradtime = get_trade_time("IH")
    dfdata,dfout = raw2tick(df, "a")  # 豆类1号
    dfreturn = tick2min(dfdata)
    print(dfreturn)
else:
    build_trade_time()
